<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>原型(prototype)</title>
  </head>

  <body>

  </body>
  <script>
    /*
    原型:
        1.是构造函数的一个属性，是一个对象，是在我们创建构造函数的时候 系统 自动分配的
           作用是给 构造函数的 实例对象 提供方法
        2.可以通过构造函数.prototype 得到   

     总结：
         1.当调用对象的属性和方法时，先去找对象本身的属性和方法，如果没有找到该属性和方法，则会去原型里调用属性和方法
           如果对象本身没有该属性或方法，原型里也没有该属性和方法，则会报错
         2.constructor记录了创建该对象的构造函数
         1. 原型对象 - 作用是给实例对象提供方法
         2. 构造函数.prototype 和 实例对象.__proto__
         3. 有prorotype属性是 构造函数  ，有 __proto__ 属性 就是 实例对象    
    */
    function Person(name, age, gender) {
      this.name = name
      this.age = age
      this.gender = gender
      this.sayHi = () => {
        console.log("构造函数里的sayHi");
      }
    }

    Person.prototype.sayHi = function () {
      console.log('sayHi被调用了');
    }
    // console.dir(Person)
    //console.log(Person.prototype);


    let p1 = new Person()
    let p2 = new Person()

    // 2.证明 原型的 constructor 属性就是构造函数
    // constructor记录了创建该对象的构造函数
    //console.log(Person.prototype.constructor === Person); //true
    console.log(p1.constructor === Person); //true

    //当调用对象的属性和方法时，先去找对象本身的属性和方法，如果没有找到该属性和方法，则会去原型里调用属性和方法
    //如果对象本身没有该属性或方法，原型里也没有该属性和方法，则会报错
    //p1.sayHi()
    // p2.sayHi()
    // console.log(p1);
    // console.log(p2);

    //1.证明 实例对象的 __proto__ 就是 构造函数的prototype
    // console.log(p1.__proto__ === p2.__proto__); //true
    // console.log(p1.__proto__ === Person.prototype); //true
    //console.log(p2.__proto__ === Person.prototype); //true
    console.log(p2);
    console.log(Person);
    console.log(p2.__proto__);
    console.log(Person.prototype);
  </script>

</html>